LAST_PROP = PROP_ACTION_NAME
};
+enum {
+ LABEL_CHILD,
+ ICON_CHILD,
+ WIDGET_CHILD
+};
+
static void gtk_button_finalize (GObject *object);
static void gtk_button_dispose (GObject *object);
int baseline,
GtkAllocation *out_clip,
gpointer data);
+static void gtk_button_set_child_type (GtkButton *button, guint child_type);
static GParamSpec *props[LAST_PROP] = { NULL, };
static guint button_signals[LAST_SIGNAL] = { 0 };
G_ADD_PRIVATE (GtkButton)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, gtk_button_actionable_iface_init))
+static void
+gtk_button_add (GtkContainer *container, GtkWidget *child)
+{
+ GtkButton *button = GTK_BUTTON (container);
+
+ if (button->priv->child_type != WIDGET_CHILD)
+ gtk_container_remove (container, gtk_bin_get_child (GTK_BIN (button)));
+
+ gtk_button_set_child_type (button, WIDGET_CHILD);
+
+ GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, child);
+}
+
+static void
+gtk_button_remove (GtkContainer *container, GtkWidget *child)
+{
+ GtkButton *button = GTK_BUTTON (container);
+
+ gtk_button_set_child_type (button, WIDGET_CHILD);
+
+ GTK_CONTAINER_CLASS (gtk_button_parent_class)->remove (container, child);
+}
+
static void
gtk_button_class_init (GtkButtonClass *klass)
{
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
gobject_class = G_OBJECT_CLASS (klass);
widget_class = (GtkWidgetClass*) klass;
-
+ container_class = GTK_CONTAINER_CLASS (klass);
+
gobject_class->dispose = gtk_button_dispose;
gobject_class->finalize = gtk_button_finalize;
gobject_class->set_property = gtk_button_set_property;
widget_class->state_changed = gtk_button_state_changed;
widget_class->grab_notify = gtk_button_grab_notify;
+ container_class->add = gtk_button_add;
+ container_class->remove = gtk_button_remove;
+
klass->clicked = NULL;
klass->activate = gtk_real_button_activate;
gtk_button_do_release (button, FALSE);
}
+static void
+gtk_button_set_child_type (GtkButton *button, guint child_type)
+{
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
+ if (priv->child_type == child_type)
+ return;
+
+ if (child_type != LABEL_CHILD)
+ g_object_notify_by_pspec (G_OBJECT (button), props[PROP_LABEL]);
+ else if (child_type != ICON_CHILD)
+ g_object_notify_by_pspec (G_OBJECT (button), props[PROP_ICON_NAME]);
+
+ priv->child_type = child_type;
+}
+
static void
gtk_button_init (GtkButton *button)
{
gtk_widget_set_receives_default (GTK_WIDGET (button), TRUE);
gtk_widget_set_has_window (GTK_WIDGET (button), FALSE);
- priv->label_text = NULL;
-
- priv->constructed = FALSE;
priv->in_button = FALSE;
priv->button_down = FALSE;
priv->use_underline = FALSE;
+ priv->child_type = WIDGET_CHILD;
priv->gesture = gtk_gesture_multi_press_new (GTK_WIDGET (button));
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->gesture), FALSE);
GtkButton *button = GTK_BUTTON (object);
GtkButtonPrivate *priv = button->priv;
- g_clear_pointer (&priv->label_text, g_free);
g_clear_object (&priv->gesture);
g_clear_object (&priv->gadget);
switch (prop_id)
{
case PROP_LABEL:
- g_value_set_string (value, priv->label_text);
+ g_value_set_string (value, gtk_button_get_label (button));
break;
case PROP_RELIEF:
g_value_set_enum (value, gtk_button_get_relief (button));
context = gtk_widget_get_style_context (GTK_WIDGET (button));
- g_free (priv->label_text);
- priv->label_text = g_strdup (label);
-
child = gtk_bin_get_child (GTK_BIN (button));
- if (child != NULL)
+ if (priv->child_type != LABEL_CHILD || child == NULL)
{
- if (!priv->constructed || !GTK_IS_LABEL (child))
- {
- gtk_container_remove (GTK_CONTAINER (button), child);
- }
- else
+ if (child != NULL)
+ gtk_container_remove (GTK_CONTAINER (button), child);
+
+ child = gtk_label_new (NULL);
+ if (priv->use_underline)
{
- gtk_label_set_label (GTK_LABEL (child), label);
- return;
+ gtk_label_set_use_underline (GTK_LABEL (child), priv->use_underline);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (child), GTK_WIDGET (button));
}
- }
-
- gtk_style_context_remove_class (context, "image-button");
- gtk_style_context_add_class (context, "text-button");
-
- if (label != NULL)
- {
- child = gtk_label_new (label);
- gtk_label_set_use_underline (GTK_LABEL (child), priv->use_underline);
gtk_widget_show (child);
gtk_container_add (GTK_CONTAINER (button), child);
- priv->constructed = TRUE;
+ gtk_style_context_remove_class (context, "image-button");
+ gtk_style_context_add_class (context, "text-button");
}
+ gtk_label_set_label (GTK_LABEL (child), label);
+ gtk_button_set_child_type (button, LABEL_CHILD);
g_object_notify_by_pspec (G_OBJECT (button), props[PROP_LABEL]);
}
const gchar *
gtk_button_get_label (GtkButton *button)
{
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
- return button->priv->label_text;
+ if (priv->child_type == LABEL_CHILD)
+ {
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
+ return gtk_label_get_label (GTK_LABEL (child));
+ }
+
+ return NULL;
}
/**
if (use_underline != priv->use_underline)
{
- priv->use_underline = use_underline;
-
- g_object_notify_by_pspec (G_OBJECT (button), props[PROP_USE_UNDERLINE]);
- }
-
- if (priv->constructed)
- {
- GtkWidget *child;
- child = gtk_bin_get_child (GTK_BIN (button));
-
- if (child != NULL && GTK_IS_LABEL (child))
+ if (priv->child_type == LABEL_CHILD)
{
+ GtkWidget *child;
+ child = gtk_bin_get_child (GTK_BIN (button));
+
gtk_label_set_use_underline (GTK_LABEL (child), use_underline);
gtk_label_set_mnemonic_widget (GTK_LABEL (child), GTK_WIDGET (button));
}
+
+ priv->use_underline = use_underline;
+ g_object_notify_by_pspec (G_OBJECT (button), props[PROP_USE_UNDERLINE]);
}
}
/**
* gtk_button_set_icon_name:
+ * @button: A #GtkButton
+ * @icon_name: A icon name
*
+ * Adds a #GtkImage with the given icon name as a child. The icon will be
+ * of size %GTK_ICON_SIZE_BUTTON. If @button already contains a child widget,
+ * that child widget will be removed and replaced with the image.
*/
void
gtk_button_set_icon_name (GtkButton *button,
child = gtk_bin_get_child (GTK_BIN (button));
context = gtk_widget_get_style_context (GTK_WIDGET (button));
- if (child != NULL)
+ if (priv->child_type != ICON_CHILD || child == NULL)
{
- if (!priv->constructed || !GTK_IS_IMAGE (child))
- {
- gtk_container_remove (GTK_CONTAINER (button), child);
- }
- else
- {
- gtk_image_set_from_icon_name (GTK_IMAGE (child), icon_name, GTK_ICON_SIZE_BUTTON);
- return;
- }
- }
+ if (child != NULL)
+ gtk_container_remove (GTK_CONTAINER (button), child);
- gtk_style_context_remove_class (context, "text-button");
- gtk_style_context_add_class (context, "image-button");
+ child = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (child);
+ gtk_container_add (GTK_CONTAINER (button), child);
+ gtk_style_context_remove_class (context, "text-button");
+ gtk_style_context_add_class (context, "image-button");
+ }
+ else
+ {
+ gtk_image_set_from_icon_name (GTK_IMAGE (child), icon_name, GTK_ICON_SIZE_BUTTON);
+ }
- child = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (child);
- gtk_container_add (GTK_CONTAINER (button), child);
- priv->constructed = TRUE;
+ gtk_button_set_child_type (button, ICON_CHILD);
g_object_notify_by_pspec (G_OBJECT (button), props[PROP_ICON_NAME]);
}
const char *
gtk_button_get_icon_name (GtkButton *button)
{
+ GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
- if (button->priv->constructed)
+ if (priv->child_type == ICON_CHILD)
{
+ const char *icon_name;
GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
+ gtk_image_get_icon_name (GTK_IMAGE (child), &icon_name, NULL);
- if (GTK_IS_IMAGE (child))
- {
- const char *icon_name;
- gtk_image_get_icon_name (GTK_IMAGE (child), &icon_name, NULL);
- return icon_name;
- }
+ return icon_name;
}
+
return NULL;
}
/* Style args */
PROP_BACKGROUND,
PROP_FOREGROUND,
- PROP_BACKGROUND_GDK,
- PROP_FOREGROUND_GDK,
PROP_BACKGROUND_RGBA,
PROP_FOREGROUND_RGBA,
PROP_FONT,
PROP_TABS,
PROP_INVISIBLE,
PROP_PARAGRAPH_BACKGROUND,
- PROP_PARAGRAPH_BACKGROUND_GDK,
PROP_PARAGRAPH_BACKGROUND_RGBA,
PROP_FALLBACK,
PROP_LETTER_SPACING,
dest->blue = CLAMP (src->blue, 0.0, 1.0) * 65535.0;
}
-static void
-copy_gdk_color_to_rgba (GdkColor *src,
- GdkRGBA *dest)
-{
- dest->red = src->red / 65535.;
- dest->green = src->green / 65535.;
- dest->blue = src->blue / 65535.;
- dest->alpha = 1;
-}
-
static void
set_underline_rgba (GtkTextTag *tag,
const GdkRGBA *rgba)
}
}
-
-static void
-set_bg_color (GtkTextTag *tag, GdkColor *color)
-{
- if (color)
- {
- GdkRGBA rgba;
-
- copy_gdk_color_to_rgba (color, &rgba);
- set_bg_rgba (tag, &rgba);
- }
- else
- set_bg_rgba (tag, NULL);
-}
-
-static void
-set_fg_color (GtkTextTag *tag, GdkColor *color)
-{
- if (color)
- {
- GdkRGBA rgba;
-
- copy_gdk_color_to_rgba (color, &rgba);
- set_fg_rgba (tag, &rgba);
- }
- else
- set_fg_rgba (tag, NULL);
-}
-
-static void
-set_pg_bg_color (GtkTextTag *tag, GdkColor *color)
-{
- if (color)
- {
- GdkRGBA rgba;
-
- copy_gdk_color_to_rgba (color, &rgba);
- set_pg_bg_rgba (tag, &rgba);
- }
- else
- set_pg_bg_rgba (tag, NULL);
-}
-
static PangoFontMask
get_property_font_set_mask (guint prop_id)
{
}
break;
- case PROP_BACKGROUND_GDK:
- {
- GdkColor *color = g_value_get_boxed (value);
-
- set_bg_color (text_tag, color);
- }
- break;
-
- case PROP_FOREGROUND_GDK:
- {
- GdkColor *color = g_value_get_boxed (value);
-
- set_fg_color (text_tag, color);
- }
- break;
-
case PROP_BACKGROUND_RGBA:
{
GdkRGBA *color = g_value_get_boxed (value);
set_pg_bg_rgba (text_tag, &rgba);
else
g_warning ("Don't know color '%s'", g_value_get_string (value));
-
- g_object_notify (object, "paragraph-background-gdk");
- }
- break;
-
- case PROP_PARAGRAPH_BACKGROUND_GDK:
- {
- GdkColor *color = g_value_get_boxed (value);
-
- set_pg_bg_color (text_tag, color);
}
break;
g_value_set_string (value, priv->name);
break;
- case PROP_BACKGROUND_GDK:
- g_value_set_boxed (value, &priv->values->appearance.bg_color);
- break;
-
case PROP_BACKGROUND_RGBA:
g_value_set_boxed (value, priv->values->appearance.rgba[0]);
break;
- case PROP_FOREGROUND_GDK:
- g_value_set_boxed (value, &priv->values->appearance.fg_color);
- break;
-
case PROP_FOREGROUND_RGBA:
g_value_set_boxed (value, priv->values->appearance.rgba[1]);
break;
g_value_set_boolean (value, priv->values->invisible);
break;
- case PROP_PARAGRAPH_BACKGROUND_GDK:
- g_value_set_boxed (value, priv->values->pg_bg_color);
- break;
case PROP_PARAGRAPH_BACKGROUND_RGBA:
g_value_set_boxed (value, priv->values->pg_bg_rgba);